﻿using System;
using System.Data.Entity;
using Supermodel.DomainModel;

namespace Supermodel.UOW
{
    public abstract class UnitOfWork : DbContext, IDisposable
    {
        protected UnitOfWork() : this(true) {}
        protected UnitOfWork(bool putInStack) : base()
        {
            _inStack = true;

            CommitOnDispose = true;
            if (_inStack) UnitOfWorkContext<UnitOfWork>.PushUnitOfWork(this);             
        }
        protected UnitOfWork(string databaseNameOrConnectionString): this(databaseNameOrConnectionString, true){}
        protected UnitOfWork(string databaseNameOrConnectionString, bool putInStack) : base(databaseNameOrConnectionString)
        {
            _inStack = putInStack;
            
            CommitOnDispose = true;
            if (_inStack) UnitOfWorkContext<UnitOfWork>.PushUnitOfWork(this);
        }

        public bool CommitOnDispose { get; set; }
        
        void IDisposable.Dispose()
        {
            if (CommitOnDispose) SaveChanges();

            if (_inStack)
            {
                var uow = UnitOfWorkContext<UnitOfWork>.PopUnitOfWork();
                //if (uow != this) throw new SupermodelException("UnitOfWork: POP on Dispose popped mismatched unit of work.");
            }
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Configurations
                .Add(new EFCFEnumTypeMapping())
                .Add(new BinaryFileTypeMapping());
        }
        
        private readonly bool _inStack;
    }
}
